﻿package com.snzflash.media 
{
	import com.snzflash.events.MediaEvent;
	import flash.events.AsyncErrorEvent;
	import flash.events.NetStatusEvent;
	import flash.events.ProgressEvent;
	import flash.events.TimerEvent;
	import flash.media.SoundTransform;
	import flash.media.Video;
	import flash.net.NetConnection;
	import flash.net.NetStream;
	import flash.utils.Timer;
	
	/**
	 * ...
	 * @author firsoff
	 */
	public class VideoPlayer extends Video
	{
		//public var smoothing:Boolean = true;
		public var loop:Boolean = true;
		// поток
		private var _netStream:NetStream;
		// коннектор
		private var _netConnection:NetConnection;
		// клиент обратного вызова
		private var _client:Object;
		// длительность
		private var _duration:Number;
		// текущее время
		private var _time:Number;
		// файл
		private var _source:String;
		// финиш?
		private var _finished:Boolean;
		// таймер обновяления
		private var _updateTimer:Timer;
		private var _updateInterval:Number = 250;
		private var _autoPlay:Boolean = true;
		private var _bufferTime:Number = 1.5;
		private var _volume:Number = 1;
		
		// факт получения размеров видео
		private var _videoSizeSetup:Boolean;
	
		public static const PLAYING:String = 'playing';
		public static const PAUSED:String = 'paused';
		
		public function VideoPlayer(width:int = 320, height:int = 240) 
		{
			super(width, height);
			init();
		}
		
		private function init():void
		{
			_updateTimer = new Timer(_updateInterval);
			_updateTimer.addEventListener(TimerEvent.TIMER, onTimer);
		};
		
		//public function load(url:String):void 
		//{
			//
		//}
		
		public function destroyNetStream():void 
		{
			
			
			if(_client)_client.onMetaData = null;
			
			if (_netConnection)
			{
				_netConnection.removeEventListener(NetStatusEvent.NET_STATUS, onStatus)
			}
			if (_netStream)
			{
				_netStream.removeEventListener(NetStatusEvent.NET_STATUS, onStatus);
				_netStream.removeEventListener(AsyncErrorEvent.ASYNC_ERROR, onAsyncError);
			}
			close();
			clear();
			_netConnection = null;
			_netStream = null;
		}
		
		public function play():void 
		{
			_netStream.play(_source); 
			_finished = false;
		};
		
		public function pause():void 
		{
			if(_netStream)_netStream.pause();
		};
		
		public function resume():void 
		{
			//trace(_finished && loop);
			if (_finished && loop) { play(); }
			else 
			{
				if(_netStream) _netStream.resume();
			};
			//_finished = false;
		};
		
		public function close():void 
		{
			try {_netStream.close();}
			catch (err:Error) { };
			
			try { _netConnection.close(); }
			catch (err:Error) { };
			
			if (_client)
			{
				_client.onMetaData = null;
				_client = null;
			};
		};
		
		public function seek(position:Number):void 
		{
			try 
			{
				_netStream.seek(position);
			}
			catch (err:Error){}
		}
		
		public function seekByPercent(position_percent:Number):void 
		{
			var position:Number = position_percent * _duration;
			seek(position);
		}
		
		public function destroy():void 
		{
			destroyNetStream();
			_updateTimer.stop();
			_updateTimer.removeEventListener(TimerEvent.TIMER, onTimer);
			_updateTimer = null;
		};
		
		private function onMetaData(data:Object):void
		{
			_duration = data.duration;
		};
		
		public function get duration():Number { return _duration; };
		
		public function get time():Number { return _time; };
		
		public function get autoPlay():Boolean { return _autoPlay; };
		
		public function set autoPlay(value:Boolean):void 
		{
			_autoPlay = value;
		};
		
		public function get volume():Number { return _netStream.soundTransform.volume; };
		
		public function set volume(value:Number):void 
		{
			_volume = value;
			if (!_netStream) return;
			var st:SoundTransform = new SoundTransform();
			st.volume = value;
			_netStream.soundTransform = st;
		};
		
		public function get source():String { return _source; };
		
		public function set source(value:String):void 
		{
			_source = value;
			if (!value) return;
			//trace('SOURCE : ' + value);
			_finished = false;
			_duration = _time = NaN;
			close();
			destroyNetStream();
			
			_client = new Object();
			_client.onMetaData = onMetaData;
			
			_netConnection = new NetConnection();
			_netConnection.addEventListener(NetStatusEvent.NET_STATUS, onStatus)
			_netConnection.connect(null);
			
			_netStream =  new NetStream(_netConnection);
			_netStream.addEventListener(NetStatusEvent.NET_STATUS, onStatus);
			_netStream.addEventListener(AsyncErrorEvent.ASYNC_ERROR, onAsyncError);

			_netStream.bufferTime = _bufferTime;
			_netStream.client = _client;
			attachNetStream(_netStream);
			
			if (_autoPlay) play();
			_updateTimer.start();
		};
		
		public function get finished():Boolean { return _finished; };
		
		
		
		
		
		private function onTimer(event:TimerEvent):void 
		{
			_time = _netStream.time;
			//trace(_netStream.bytesLoaded, _netStream.bytesTotal);
			
			if (_duration > 0) 
			{
				var e2:MediaEvent = new MediaEvent(MediaEvent.PLAYING_PROGRESS, false, false,  _netStream.time /  duration);
				dispatchEvent(e2);
			};
			
			if (_netStream.bytesTotal > 0)
			{
				var e:MediaEvent = new MediaEvent(MediaEvent.LOADING_PROGRESS, false, false,  _netStream.bytesLoaded /  _netStream.bytesTotal);
				dispatchEvent(e);
			};
		};
		
		private function onStatus(event:NetStatusEvent):void 
		{
			//trace(event.info.code, _finished);
			switch (event.info.code) {
                case "NetConnection.Connect.Success":
                    //connectStream();
				break;
				
                case "NetStream.Play.StreamNotFound":
                    //trace("Unable to locate video: " + videoURL);
                break;
					
				case "NetStream.Buffer.Full":
					if (_videoSizeSetup) return;
					dispatchEvent(new MediaEvent(MediaEvent.VIDEO_INIT, false, false, { width:videoWidth, height:videoHeight } ));
					
                break;
				
				case "NetStream.Play.Stop":
					dispatchEvent(new MediaEvent(MediaEvent.STREAM_FINISH));
                break;
            }

		};
		
		private function onAsyncError(event:AsyncErrorEvent):void 
		{
			
		};
	}

}